home *** CD-ROM | disk | FTP | other *** search
/ Ultra Pack / UltraComputing Partner Applications.iso / SunLabs / tclTK / src / tk4.0 / tkCanvBmap.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  23KB  |  797 lines

  1. /* 
  2.  * tkCanvBmap.c --
  3.  *
  4.  *    This file implements bitmap items for canvas widgets.
  5.  *
  6.  * Copyright (c) 1992-1994 The Regents of the University of California.
  7.  * Copyright (c) 1994-1995 Sun Microsystems, Inc.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  */
  12.  
  13. static char sccsid[] = "@(#) tkCanvBmap.c 1.22 95/03/17 16:01:42";
  14.  
  15. #include <stdio.h>
  16. #include "tkInt.h"
  17. #include "tkPort.h"
  18. #include "tkCanvas.h"
  19.  
  20. /*
  21.  * The structure below defines the record for each bitmap item.
  22.  */
  23.  
  24. typedef struct BitmapItem  {
  25.     Tk_Item header;        /* Generic stuff that's the same for all
  26.                  * types.  MUST BE FIRST IN STRUCTURE. */
  27.     double x, y;        /* Coordinates of positioning point for
  28.                  * bitmap. */
  29.     Tk_Anchor anchor;        /* Where to anchor bitmap relative to
  30.                  * (x,y). */
  31.     Pixmap bitmap;        /* Bitmap to display in window. */
  32.     XColor *fgColor;        /* Foreground color to use for bitmap. */
  33.     XColor *bgColor;        /* Background color to use for bitmap. */
  34.     GC gc;            /* Graphics context to use for drawing
  35.                  * bitmap on screen. */
  36. } BitmapItem;
  37.  
  38. /*
  39.  * Information used for parsing configuration specs:
  40.  */
  41.  
  42. static Tk_ConfigSpec configSpecs[] = {
  43.     {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
  44.     "center", Tk_Offset(BitmapItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
  45.     {TK_CONFIG_COLOR, "-background", (char *) NULL, (char *) NULL,
  46.     (char *) NULL, Tk_Offset(BitmapItem, bgColor), TK_CONFIG_NULL_OK},
  47.     {TK_CONFIG_BITMAP, "-bitmap", (char *) NULL, (char *) NULL,
  48.     (char *) NULL, Tk_Offset(BitmapItem, bitmap), TK_CONFIG_NULL_OK},
  49.     {TK_CONFIG_COLOR, "-foreground", (char *) NULL, (char *) NULL,
  50.     "black", Tk_Offset(BitmapItem, fgColor), 0},
  51.     {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
  52.     (char *) NULL, 0, TK_CONFIG_NULL_OK, &tk_CanvasTagsOption},
  53.     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
  54.     (char *) NULL, 0, 0}
  55. };
  56.  
  57. /*
  58.  * Prototypes for procedures defined in this file:
  59.  */
  60.  
  61. static int        BitmapCoords _ANSI_ARGS_((Tcl_Interp *interp,
  62.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  63.                 char **argv));
  64. static int        BitmapToArea _ANSI_ARGS_((Tk_Canvas canvas,
  65.                 Tk_Item *itemPtr, double *rectPtr));
  66. static double        BitmapToPoint _ANSI_ARGS_((Tk_Canvas canvas,
  67.                 Tk_Item *itemPtr, double *coordPtr));
  68. static int        BitmapToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
  69.                 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
  70. static void        ComputeBitmapBbox _ANSI_ARGS_((Tk_Canvas canvas,
  71.                 BitmapItem *bmapPtr));
  72. static int        ConfigureBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  73.                 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
  74.                 char **argv, int flags));
  75. static int        CreateBitmap _ANSI_ARGS_((Tcl_Interp *interp,
  76.                 Tk_Canvas canvas, struct Tk_Item *itemPtr,
  77.                 int argc, char **argv));
  78. static void        DeleteBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  79.                 Tk_Item *itemPtr, Display *display));
  80. static void        DisplayBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  81.                 Tk_Item *itemPtr, Display *display, Drawable dst,
  82.                 int x, int y, int width, int height));
  83. static void        ScaleBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  84.                 Tk_Item *itemPtr, double originX, double originY,
  85.                 double scaleX, double scaleY));
  86. static void        TranslateBitmap _ANSI_ARGS_((Tk_Canvas canvas,
  87.                 Tk_Item *itemPtr, double deltaX, double deltaY));
  88.  
  89. /*
  90.  * The structures below defines the bitmap item type in terms of
  91.  * procedures that can be invoked by generic item code.
  92.  */
  93.  
  94. Tk_ItemType tkBitmapType = {
  95.     "bitmap",                /* name */
  96.     sizeof(BitmapItem),            /* itemSize */
  97.     CreateBitmap,            /* createProc */
  98.     configSpecs,            /* configSpecs */
  99.     ConfigureBitmap,            /* configureProc */
  100.     BitmapCoords,            /* coordProc */
  101.     DeleteBitmap,            /* deleteProc */
  102.     DisplayBitmap,            /* displayProc */
  103.     0,                    /* alwaysRedraw */
  104.     BitmapToPoint,            /* pointProc */
  105.     BitmapToArea,            /* areaProc */
  106.     BitmapToPostscript,            /* postscriptProc */
  107.     ScaleBitmap,            /* scaleProc */
  108.     TranslateBitmap,            /* translateProc */
  109.     (Tk_ItemIndexProc *) NULL,        /* indexProc */
  110.     (Tk_ItemCursorProc *) NULL,        /* icursorProc */
  111.     (Tk_ItemSelectionProc *) NULL,    /* selectionProc */
  112.     (Tk_ItemInsertProc *) NULL,        /* insertProc */
  113.     (Tk_ItemDCharsProc *) NULL,        /* dTextProc */
  114.     (Tk_ItemType *) NULL        /* nextPtr */
  115. };
  116.  
  117. /*
  118.  *--------------------------------------------------------------
  119.  *
  120.  * CreateBitmap --
  121.  *
  122.  *    This procedure is invoked to create a new bitmap
  123.  *    item in a canvas.
  124.  *
  125.  * Results:
  126.  *    A standard Tcl return value.  If an error occurred in
  127.  *    creating the item, then an error message is left in
  128.  *    interp->result;  in this case itemPtr is left uninitialized,
  129.  *    so it can be safely freed by the caller.
  130.  *
  131.  * Side effects:
  132.  *    A new bitmap item is created.
  133.  *
  134.  *--------------------------------------------------------------
  135.  */
  136.  
  137. static int
  138. CreateBitmap(interp, canvas, itemPtr, argc, argv)
  139.     Tcl_Interp *interp;            /* Interpreter for error reporting. */
  140.     Tk_Canvas canvas;            /* Canvas to hold new item. */
  141.     Tk_Item *itemPtr;            /* Record to hold new item;  header
  142.                      * has been initialized by caller. */
  143.     int argc;                /* Number of arguments in argv. */
  144.     char **argv;            /* Arguments describing rectangle. */
  145. {
  146.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  147.  
  148.     if (argc < 2) {
  149.     Tcl_AppendResult(interp, "wrong # args:  should be \"",
  150.         Tk_PathName(Tk_CanvasTkwin(canvas)), "\" create ",
  151.         itemPtr->typePtr->name, " x y ?options?",
  152.         (char *) NULL);
  153.     return TCL_ERROR;
  154.     }
  155.  
  156.     /*
  157.      * Initialize item's record.
  158.      */
  159.  
  160.     bmapPtr->anchor = TK_ANCHOR_CENTER;
  161.     bmapPtr->bitmap = None;
  162.     bmapPtr->fgColor = NULL;
  163.     bmapPtr->bgColor = NULL;
  164.     bmapPtr->gc = None;
  165.  
  166.     /*
  167.      * Process the arguments to fill in the item record.
  168.      */
  169.  
  170.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
  171.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
  172.         != TCL_OK)) {
  173.     return TCL_ERROR;
  174.     }
  175.  
  176.     if (ConfigureBitmap(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
  177.     DeleteBitmap(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
  178.     return TCL_ERROR;
  179.     }
  180.     return TCL_OK;
  181. }
  182.  
  183. /*
  184.  *--------------------------------------------------------------
  185.  *
  186.  * BitmapCoords --
  187.  *
  188.  *    This procedure is invoked to process the "coords" widget
  189.  *    command on bitmap items.  See the user documentation for
  190.  *    details on what it does.
  191.  *
  192.  * Results:
  193.  *    Returns TCL_OK or TCL_ERROR, and sets interp->result.
  194.  *
  195.  * Side effects:
  196.  *    The coordinates for the given item may be changed.
  197.  *
  198.  *--------------------------------------------------------------
  199.  */
  200.  
  201. static int
  202. BitmapCoords(interp, canvas, itemPtr, argc, argv)
  203.     Tcl_Interp *interp;            /* Used for error reporting. */
  204.     Tk_Canvas canvas;            /* Canvas containing item. */
  205.     Tk_Item *itemPtr;            /* Item whose coordinates are to be
  206.                      * read or modified. */
  207.     int argc;                /* Number of coordinates supplied in
  208.                      * argv. */
  209.     char **argv;            /* Array of coordinates: x1, y1,
  210.                      * x2, y2, ... */
  211. {
  212.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  213.     char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
  214.  
  215.     if (argc == 0) {
  216.     Tcl_PrintDouble(interp, bmapPtr->x, x);
  217.     Tcl_PrintDouble(interp, bmapPtr->y, y);
  218.     Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
  219.     } else if (argc == 2) {
  220.     if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &bmapPtr->x) != TCL_OK)
  221.         || (Tk_CanvasGetCoord(interp, canvas, argv[1], &bmapPtr->y)
  222.             != TCL_OK)) {
  223.         return TCL_ERROR;
  224.     }
  225.     ComputeBitmapBbox(canvas, bmapPtr);
  226.     } else {
  227.     sprintf(interp->result,
  228.         "wrong # coordinates:  expected 0 or 2, got %d", argc);
  229.     return TCL_ERROR;
  230.     }
  231.     return TCL_OK;
  232. }
  233.  
  234. /*
  235.  *--------------------------------------------------------------
  236.  *
  237.  * ConfigureBitmap --
  238.  *
  239.  *    This procedure is invoked to configure various aspects
  240.  *    of a bitmap item, such as its anchor position.
  241.  *
  242.  * Results:
  243.  *    A standard Tcl result code.  If an error occurs, then
  244.  *    an error message is left in interp->result.
  245.  *
  246.  * Side effects:
  247.  *    Configuration information may be set for itemPtr.
  248.  *
  249.  *--------------------------------------------------------------
  250.  */
  251.  
  252. static int
  253. ConfigureBitmap(interp, canvas, itemPtr, argc, argv, flags)
  254.     Tcl_Interp *interp;        /* Used for error reporting. */
  255.     Tk_Canvas canvas;        /* Canvas containing itemPtr. */
  256.     Tk_Item *itemPtr;        /* Bitmap item to reconfigure. */
  257.     int argc;            /* Number of elements in argv.  */
  258.     char **argv;        /* Arguments describing things to configure. */
  259.     int flags;            /* Flags to pass to Tk_ConfigureWidget. */
  260. {
  261.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  262.     XGCValues gcValues;
  263.     GC newGC;
  264.     Tk_Window tkwin;
  265.     unsigned long mask;
  266.  
  267.     tkwin = Tk_CanvasTkwin(canvas);
  268.     if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
  269.         (char *) bmapPtr, flags) != TCL_OK) {
  270.     return TCL_ERROR;
  271.     }
  272.  
  273.     /*
  274.      * A few of the options require additional processing, such as those
  275.      * that determine the graphics context.
  276.      */
  277.  
  278.     gcValues.foreground = bmapPtr->fgColor->pixel;
  279.     mask = GCForeground;
  280.     if (bmapPtr->bgColor != NULL) {
  281.     gcValues.background = bmapPtr->bgColor->pixel;
  282.     mask |= GCBackground;
  283.     } else {
  284.     gcValues.clip_mask = bmapPtr->bitmap;
  285.     mask |= GCClipMask;
  286.     }
  287.     newGC = Tk_GetGC(tkwin, mask, &gcValues);
  288.     if (bmapPtr->gc != None) {
  289.     Tk_FreeGC(Tk_Display(tkwin), bmapPtr->gc);
  290.     }
  291.     bmapPtr->gc = newGC;
  292.  
  293.     ComputeBitmapBbox(canvas, bmapPtr);
  294.  
  295.     return TCL_OK;
  296. }
  297.  
  298. /*
  299.  *--------------------------------------------------------------
  300.  *
  301.  * DeleteBitmap --
  302.  *
  303.  *    This procedure is called to clean up the data structure
  304.  *    associated with a bitmap item.
  305.  *
  306.  * Results:
  307.  *    None.
  308.  *
  309.  * Side effects:
  310.  *    Resources associated with itemPtr are released.
  311.  *
  312.  *--------------------------------------------------------------
  313.  */
  314.  
  315. static void
  316. DeleteBitmap(canvas, itemPtr, display)
  317.     Tk_Canvas canvas;            /* Info about overall canvas widget. */
  318.     Tk_Item *itemPtr;            /* Item that is being deleted. */
  319.     Display *display;            /* Display containing window for
  320.                      * canvas. */
  321. {
  322.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  323.  
  324.     if (bmapPtr->bitmap != None) {
  325.     Tk_FreeBitmap(display, bmapPtr->bitmap);
  326.     }
  327.     if (bmapPtr->fgColor != NULL) {
  328.     Tk_FreeColor(bmapPtr->fgColor);
  329.     }
  330.     if (bmapPtr->bgColor != NULL) {
  331.     Tk_FreeColor(bmapPtr->bgColor);
  332.     }
  333.     if (bmapPtr->gc != NULL) {
  334.     Tk_FreeGC(display, bmapPtr->gc);
  335.     }
  336. }
  337.  
  338. /*
  339.  *--------------------------------------------------------------
  340.  *
  341.  * ComputeBitmapBbox --
  342.  *
  343.  *    This procedure is invoked to compute the bounding box of
  344.  *    all the pixels that may be drawn as part of a bitmap item.
  345.  *    This procedure is where the child bitmap's placement is
  346.  *    computed.
  347.  *
  348.  * Results:
  349.  *    None.
  350.  *
  351.  * Side effects:
  352.  *    The fields x1, y1, x2, and y2 are updated in the header
  353.  *    for itemPtr.
  354.  *
  355.  *--------------------------------------------------------------
  356.  */
  357.  
  358.     /* ARGSUSED */
  359. static void
  360. ComputeBitmapBbox(canvas, bmapPtr)
  361.     Tk_Canvas canvas;            /* Canvas that contains item. */
  362.     BitmapItem *bmapPtr;        /* Item whose bbox is to be
  363.                      * recomputed. */
  364. {
  365.     int width, height;
  366.     int x, y;
  367.  
  368.     x = bmapPtr->x + 0.5;
  369.     y = bmapPtr->y + 0.5;
  370.  
  371.     if (bmapPtr->bitmap == None) {
  372.     bmapPtr->header.x1 = bmapPtr->header.x2 = x;
  373.     bmapPtr->header.y1 = bmapPtr->header.y2 = y;
  374.     return;
  375.     }
  376.  
  377.     /*
  378.      * Compute location and size of bitmap, using anchor information.
  379.      */
  380.  
  381.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap,
  382.         &width, &height);
  383.     switch (bmapPtr->anchor) {
  384.     case TK_ANCHOR_N:
  385.         x -= width/2;
  386.         break;
  387.     case TK_ANCHOR_NE:
  388.         x -= width;
  389.         break;
  390.     case TK_ANCHOR_E:
  391.         x -= width;
  392.         y -= height/2;
  393.         break;
  394.     case TK_ANCHOR_SE:
  395.         x -= width;
  396.         y -= height;
  397.         break;
  398.     case TK_ANCHOR_S:
  399.         x -= width/2;
  400.         y -= height;
  401.         break;
  402.     case TK_ANCHOR_SW:
  403.         y -= height;
  404.         break;
  405.     case TK_ANCHOR_W:
  406.         y -= height/2;
  407.         break;
  408.     case TK_ANCHOR_NW:
  409.         break;
  410.     case TK_ANCHOR_CENTER:
  411.         x -= width/2;
  412.         y -= height/2;
  413.         break;
  414.     }
  415.  
  416.     /*
  417.      * Store the information in the item header.
  418.      */
  419.  
  420.     bmapPtr->header.x1 = x;
  421.     bmapPtr->header.y1 = y;
  422.     bmapPtr->header.x2 = x + width;
  423.     bmapPtr->header.y2 = y + height;
  424. }
  425.  
  426. /*
  427.  *--------------------------------------------------------------
  428.  *
  429.  * DisplayBitmap --
  430.  *
  431.  *    This procedure is invoked to draw a bitmap item in a given
  432.  *    drawable.
  433.  *
  434.  * Results:
  435.  *    None.
  436.  *
  437.  * Side effects:
  438.  *    ItemPtr is drawn in drawable using the transformation
  439.  *    information in canvas.
  440.  *
  441.  *--------------------------------------------------------------
  442.  */
  443.  
  444. static void
  445. DisplayBitmap(canvas, itemPtr, display, drawable, x, y, width, height)
  446.     Tk_Canvas canvas;            /* Canvas that contains item. */
  447.     Tk_Item *itemPtr;            /* Item to be displayed. */
  448.     Display *display;            /* Display on which to draw item. */
  449.     Drawable drawable;            /* Pixmap or window in which to draw
  450.                      * item. */
  451.     int x, y, width, height;        /* Describes region of canvas that
  452.                      * must be redisplayed (not used). */
  453. {
  454.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  455.     int bmapX, bmapY, bmapWidth, bmapHeight;
  456.     short drawableX, drawableY;
  457.  
  458.     /*
  459.      * If the area being displayed doesn't cover the whole bitmap,
  460.      * then only redisplay the part of the bitmap that needs
  461.      * redisplay.
  462.      */
  463.  
  464.     if (bmapPtr->bitmap != None) {
  465.     if (x > bmapPtr->header.x1) {
  466.         bmapX = x - bmapPtr->header.x1;
  467.         bmapWidth = bmapPtr->header.x2 - x;
  468.     } else {
  469.         bmapX = 0;
  470.         if ((x+width) < bmapPtr->header.x2) {
  471.         bmapWidth = x + width - bmapPtr->header.x1;
  472.         } else {
  473.         bmapWidth = bmapPtr->header.x2 - bmapPtr->header.x1;
  474.         }
  475.     }
  476.     if (y > bmapPtr->header.y1) {
  477.         bmapY = y - bmapPtr->header.y1;
  478.         bmapHeight = bmapPtr->header.y2 - y;
  479.     } else {
  480.         bmapY = 0;
  481.         if ((y+height) < bmapPtr->header.y2) {
  482.         bmapHeight = y + height - bmapPtr->header.y1;
  483.         } else {
  484.         bmapHeight = bmapPtr->header.y2 - bmapPtr->header.y1;
  485.         }
  486.     }
  487.     Tk_CanvasDrawableCoords(canvas,
  488.         (double) (bmapPtr->header.x1 + bmapX),
  489.         (double) (bmapPtr->header.y1 + bmapY),
  490.         &drawableX, &drawableY);
  491.  
  492.     /*
  493.      * Must modify the mask origin within the graphics context
  494.      * to line up with the bitmap's origin (in order to make
  495.      * bitmaps with "-background {}" work right).
  496.      */
  497.  
  498.     XSetClipOrigin(display, bmapPtr->gc, drawableX - bmapX,
  499.         drawableY - bmapY);
  500.     XCopyPlane(display, bmapPtr->bitmap, drawable,
  501.         bmapPtr->gc, bmapX, bmapY, (unsigned int) bmapWidth,
  502.         (unsigned int) bmapHeight, drawableX, drawableY, 1);
  503.     }
  504. }
  505.  
  506. /*
  507.  *--------------------------------------------------------------
  508.  *
  509.  * BitmapToPoint --
  510.  *
  511.  *    Computes the distance from a given point to a given
  512.  *    rectangle, in canvas units.
  513.  *
  514.  * Results:
  515.  *    The return value is 0 if the point whose x and y coordinates
  516.  *    are coordPtr[0] and coordPtr[1] is inside the bitmap.  If the
  517.  *    point isn't inside the bitmap then the return value is the
  518.  *    distance from the point to the bitmap.
  519.  *
  520.  * Side effects:
  521.  *    None.
  522.  *
  523.  *--------------------------------------------------------------
  524.  */
  525.  
  526.     /* ARGSUSED */
  527. static double
  528. BitmapToPoint(canvas, itemPtr, coordPtr)
  529.     Tk_Canvas canvas;        /* Canvas containing item. */
  530.     Tk_Item *itemPtr;        /* Item to check against point. */
  531.     double *coordPtr;        /* Pointer to x and y coordinates. */
  532. {
  533.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  534.     double x1, x2, y1, y2, xDiff, yDiff;
  535.  
  536.     x1 = bmapPtr->header.x1;
  537.     y1 = bmapPtr->header.y1;
  538.     x2 = bmapPtr->header.x2;
  539.     y2 = bmapPtr->header.y2;
  540.  
  541.     /*
  542.      * Point is outside rectangle.
  543.      */
  544.  
  545.     if (coordPtr[0] < x1) {
  546.     xDiff = x1 - coordPtr[0];
  547.     } else if (coordPtr[0] > x2)  {
  548.     xDiff = coordPtr[0] - x2;
  549.     } else {
  550.     xDiff = 0;
  551.     }
  552.  
  553.     if (coordPtr[1] < y1) {
  554.     yDiff = y1 - coordPtr[1];
  555.     } else if (coordPtr[1] > y2)  {
  556.     yDiff = coordPtr[1] - y2;
  557.     } else {
  558.     yDiff = 0;
  559.     }
  560.  
  561.     return hypot(xDiff, yDiff);
  562. }
  563.  
  564. /*
  565.  *--------------------------------------------------------------
  566.  *
  567.  * BitmapToArea --
  568.  *
  569.  *    This procedure is called to determine whether an item
  570.  *    lies entirely inside, entirely outside, or overlapping
  571.  *    a given rectangle.
  572.  *
  573.  * Results:
  574.  *    -1 is returned if the item is entirely outside the area
  575.  *    given by rectPtr, 0 if it overlaps, and 1 if it is entirely
  576.  *    inside the given area.
  577.  *
  578.  * Side effects:
  579.  *    None.
  580.  *
  581.  *--------------------------------------------------------------
  582.  */
  583.  
  584.     /* ARGSUSED */
  585. static int
  586. BitmapToArea(canvas, itemPtr, rectPtr)
  587.     Tk_Canvas canvas;        /* Canvas containing item. */
  588.     Tk_Item *itemPtr;        /* Item to check against rectangle. */
  589.     double *rectPtr;        /* Pointer to array of four coordinates
  590.                  * (x1, y1, x2, y2) describing rectangular
  591.                  * area.  */
  592. {
  593.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  594.  
  595.     if ((rectPtr[2] <= bmapPtr->header.x1)
  596.         || (rectPtr[0] >= bmapPtr->header.x2)
  597.         || (rectPtr[3] <= bmapPtr->header.y1)
  598.         || (rectPtr[1] >= bmapPtr->header.y2)) {
  599.     return -1;
  600.     }
  601.     if ((rectPtr[0] <= bmapPtr->header.x1)
  602.         && (rectPtr[1] <= bmapPtr->header.y1)
  603.         && (rectPtr[2] >= bmapPtr->header.x2)
  604.         && (rectPtr[3] >= bmapPtr->header.y2)) {
  605.     return 1;
  606.     }
  607.     return 0;
  608. }
  609.  
  610. /*
  611.  *--------------------------------------------------------------
  612.  *
  613.  * ScaleBitmap --
  614.  *
  615.  *    This procedure is invoked to rescale a bitmap item in a
  616.  *    canvas.  It is one of the standard item procedures for
  617.  *    bitmap items, and is invoked by the generic canvas code.
  618.  *
  619.  * Results:
  620.  *    None.
  621.  *
  622.  * Side effects:
  623.  *    The item referred to by itemPtr is rescaled so that the
  624.  *    following transformation is applied to all point coordinates:
  625.  *        x' = originX + scaleX*(x-originX)
  626.  *        y' = originY + scaleY*(y-originY)
  627.  *
  628.  *--------------------------------------------------------------
  629.  */
  630.  
  631. static void
  632. ScaleBitmap(canvas, itemPtr, originX, originY, scaleX, scaleY)
  633.     Tk_Canvas canvas;            /* Canvas containing rectangle. */
  634.     Tk_Item *itemPtr;            /* Rectangle to be scaled. */
  635.     double originX, originY;        /* Origin about which to scale item. */
  636.     double scaleX;            /* Amount to scale in X direction. */
  637.     double scaleY;            /* Amount to scale in Y direction. */
  638. {
  639.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  640.  
  641.     bmapPtr->x = originX + scaleX*(bmapPtr->x - originX);
  642.     bmapPtr->y = originY + scaleY*(bmapPtr->y - originY);
  643.     ComputeBitmapBbox(canvas, bmapPtr);
  644. }
  645.  
  646. /*
  647.  *--------------------------------------------------------------
  648.  *
  649.  * TranslateBitmap --
  650.  *
  651.  *    This procedure is called to move an item by a given amount.
  652.  *
  653.  * Results:
  654.  *    None.
  655.  *
  656.  * Side effects:
  657.  *    The position of the item is offset by (xDelta, yDelta), and
  658.  *    the bounding box is updated in the generic part of the item
  659.  *    structure.
  660.  *
  661.  *--------------------------------------------------------------
  662.  */
  663.  
  664. static void
  665. TranslateBitmap(canvas, itemPtr, deltaX, deltaY)
  666.     Tk_Canvas canvas;            /* Canvas containing item. */
  667.     Tk_Item *itemPtr;            /* Item that is being moved. */
  668.     double deltaX, deltaY;        /* Amount by which item is to be
  669.                      * moved. */
  670. {
  671.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  672.  
  673.     bmapPtr->x += deltaX;
  674.     bmapPtr->y += deltaY;
  675.     ComputeBitmapBbox(canvas, bmapPtr);
  676. }
  677.  
  678. /*
  679.  *--------------------------------------------------------------
  680.  *
  681.  * BitmapToPostscript --
  682.  *
  683.  *    This procedure is called to generate Postscript for
  684.  *    bitmap items.
  685.  *
  686.  * Results:
  687.  *    The return value is a standard Tcl result.  If an error
  688.  *    occurs in generating Postscript then an error message is
  689.  *    left in interp->result, replacing whatever used to be there.
  690.  *    If no error occurs, then Postscript for the item is appended
  691.  *    to the result.
  692.  *
  693.  * Side effects:
  694.  *    None.
  695.  *
  696.  *--------------------------------------------------------------
  697.  */
  698.  
  699. static int
  700. BitmapToPostscript(interp, canvas, itemPtr, prepass)
  701.     Tcl_Interp *interp;            /* Leave Postscript or error message
  702.                      * here. */
  703.     Tk_Canvas canvas;            /* Information about overall canvas. */
  704.     Tk_Item *itemPtr;            /* Item for which Postscript is
  705.                      * wanted. */
  706.     int prepass;            /* 1 means this is a prepass to
  707.                      * collect font information;  0 means
  708.                      * final Postscript is being created. */
  709. {
  710.     BitmapItem *bmapPtr = (BitmapItem *) itemPtr;
  711.     double x, y;
  712.     int width, height, rowsAtOnce, rowsThisTime;
  713.     int curRow;
  714.     char buffer[200];
  715.  
  716.     if (bmapPtr->bitmap == None) {
  717.     return TCL_OK;
  718.     }
  719.  
  720.     /*
  721.      * Compute the coordinates of the lower-left corner of the bitmap,
  722.      * taking into account the anchor position for the bitmp.
  723.      */
  724.  
  725.     x = bmapPtr->x;
  726.     y = Tk_CanvasPsY(canvas, bmapPtr->y);
  727.     Tk_SizeOfBitmap(Tk_Display(Tk_CanvasTkwin(canvas)), bmapPtr->bitmap,
  728.         &width, &height);
  729.     switch (bmapPtr->anchor) {
  730.     case TK_ANCHOR_NW:            y -= height;        break;
  731.     case TK_ANCHOR_N:    x -= width/2.0; y -= height;        break;
  732.     case TK_ANCHOR_NE:    x -= width;    y -= height;        break;
  733.     case TK_ANCHOR_E:    x -= width;    y -= height/2.0;    break;
  734.     case TK_ANCHOR_SE:    x -= width;                break;
  735.     case TK_ANCHOR_S:    x -= width/2.0;                break;
  736.     case TK_ANCHOR_SW:                        break;
  737.     case TK_ANCHOR_W:            y -= height/2.0;    break;
  738.     case TK_ANCHOR_CENTER:    x -= width/2.0; y -= height/2.0;    break;
  739.     }
  740.  
  741.     /*
  742.      * Color the background, if there is one.
  743.      */
  744.  
  745.     if (bmapPtr->bgColor != NULL) {
  746.     sprintf(buffer,
  747.         "%.15g %.15g moveto %d 0 rlineto 0 %d rlineto %d %s\n",
  748.         x, y, width, height, -width,"0 rlineto closepath");
  749.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  750.     if (Tk_CanvasPsColor(interp, canvas, bmapPtr->bgColor) != TCL_OK) {
  751.         return TCL_ERROR;
  752.     }
  753.     Tcl_AppendResult(interp, "fill\n", (char *) NULL);
  754.     }
  755.  
  756.     /*
  757.      * Draw the bitmap, if there is a foreground color.  If the bitmap
  758.      * is very large, then chop it up into multiple bitmaps, each
  759.      * consisting of one or more rows.  This is needed because Postscript
  760.      * can't handle single strings longer than 64 KBytes long.
  761.      */
  762.  
  763.     if (bmapPtr->fgColor != NULL) {
  764.     if (Tk_CanvasPsColor(interp, canvas, bmapPtr->fgColor) != TCL_OK) {
  765.         return TCL_ERROR;
  766.     }
  767.     if (width > 60000) {
  768.         Tcl_ResetResult(interp);
  769.         Tcl_AppendResult(interp, "can't generate Postscript",
  770.             " for bitmaps more than 60000 pixels wide",
  771.             (char *) NULL);
  772.         return TCL_ERROR;
  773.     }
  774.     rowsAtOnce = 60000/width;
  775.     if (rowsAtOnce < 1) {
  776.         rowsAtOnce = 1;
  777.     }
  778.     sprintf(buffer, "%.15g %.15g translate\n", x, y+height);
  779.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  780.     for (curRow = 0; curRow < height; curRow += rowsAtOnce) {
  781.         rowsThisTime = rowsAtOnce;
  782.         if (rowsThisTime > (height - curRow)) {
  783.         rowsThisTime = height - curRow;
  784.         }
  785.         sprintf(buffer, "0 -%.15g translate\n%d %d true matrix {\n",
  786.             (double) rowsThisTime, width, rowsThisTime);
  787.         Tcl_AppendResult(interp, buffer, (char *) NULL);
  788.         if (Tk_CanvasPsBitmap(interp, canvas, bmapPtr->bitmap,
  789.             0, curRow, width, rowsThisTime) != TCL_OK) {
  790.         return TCL_ERROR;
  791.         }
  792.         Tcl_AppendResult(interp, "\n} imagemask\n", (char *) NULL);
  793.     }
  794.     }
  795.     return TCL_OK;
  796. }
  797.